package com.linked.pay.pay.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.linked.pay.coupon.bean.po.UserCouponPO;
import com.linked.pay.coupon.mapper.IUserCouponMapper;
import com.linked.pay.feign.IScheduledTasksFeign;
import com.linked.pay.pay.bean.param.PayingParam;
import com.linked.pay.pay.bean.po.PayInfoPO;
import com.linked.pay.pay.bean.po.PayTypePO;
import com.linked.pay.pay.mapper.IPayInfoMapper;
import com.linked.pay.pay.mapper.IPayTypeMapper;
import com.linked.pay.pay.paysupply.IPaySupplyService;
import com.linked.pay.pay.paysupply.supplys.WeiXinPay;
import com.linked.pay.pay.service.IPayHandleService;
import com.linked.pay.points.bean.po.PointsInfoPO;
import com.linked.pay.points.mapper.IPointsInfoMapper;
import com.linked.pay.points.service.IPointsInfoService;
import com.linked.universal.bean.pay.param.WaitingPayCreateParam;
import com.linked.universal.bean.pay.result.PayDetailResult;
import com.linked.universal.bean.pay.result.PayResultPush;
import com.linked.universal.bean.scheduledtasks.injuiry.LinkedInquiry;
import com.linked.universal.common.LinkedResult;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;

/**
 * @author :dbq
 * @date : 2023/3/2 14:43
 * @description : desc
 */
@Service
@Slf4j
public class PayHandleServiceImpl implements IPayHandleService {

    private final ObjectMapper mapper;

    private final IPayInfoMapper payInfoMapper;

    private final IPayTypeMapper payTypeMapper;

    private final TransactionTemplate transactionTemplate;

    private final IPointsInfoService pointsInfoService;

    private IPaySupplyService paySupplyService;

    private final IPointsInfoMapper pointsInfoMapper;

    private final IUserCouponMapper userCouponMapper;

    private final IScheduledTasksFeign scheduledTasksFeign;

    @Autowired
    public PayHandleServiceImpl(IUserCouponMapper userCouponMapper,
                                IPointsInfoMapper pointsInfoMapper,
                                ObjectMapper mapper, IPayInfoMapper payInfoMapper,
                                IPayTypeMapper payTypeMapper,
                                TransactionTemplate transactionTemplate,
                                IPointsInfoService pointsInfoService,
                                IScheduledTasksFeign scheduledTasksFeign) {
        this.mapper = mapper;
        this.payInfoMapper = payInfoMapper;
        this.payTypeMapper = payTypeMapper;
        this.transactionTemplate = transactionTemplate;
        this.pointsInfoService = pointsInfoService;
        this.pointsInfoMapper = pointsInfoMapper;
        this.userCouponMapper = userCouponMapper;
        this.scheduledTasksFeign = scheduledTasksFeign;
    }

    @Override
    public PayInfoPO createWaitingPay(WaitingPayCreateParam param) throws Exception {
        PayInfoPO payInfo = new PayInfoPO(param);
        payInfoMapper.insert(payInfo);
        return payInfo;
    }

    @Override
    public PayInfoPO findPayInfo(String payId) throws Exception {
        return payInfoMapper.selectById(payId);
    }

    @Override
    public boolean paying(PayingParam param) throws Exception {
        switch (param.getPayType()) {
            case 1:
                paySupplyService = new WeiXinPay();
                break;
        }
        return transactionTemplate.execute(action -> {
            try {
                boolean ret = paySupplyService.bankcardPay();
                if (!ret) {
                    log.info("供应商支付失败！");
                    return false;
                }
                //保存支付单，支付的方式，例如：微信，支付宝，银行卡
                PayTypePO payTypePO = new PayTypePO();
                payTypePO.setPayType(param.getPayType());
                payTypePO.setBankcardId(param.getPayWayNo());
                payTypeMapper.insert(payTypePO);

                //修改支付主表
                PayInfoPO payInfo = new PayInfoPO();
                payInfo.setPayId(param.getPayId());
                payInfo.setRealAmount(param.getRealAmount());
                payInfo.setPayStatus(2);
                payInfo.setPayWayId(payTypePO.getPayWayId());
                payInfo.setCouponId(param.getCouponId());
                payInfo.setPointsAmount(param.getPointsAmount());
                payInfoMapper.updateById(payInfo);

                //修改优惠券状态-变为已使用
                if (!StringUtils.isEmpty(payInfo.getCouponId())) {
                    UserCouponPO tmp = new UserCouponPO();
                    tmp.setIfUsed(1);
                    UpdateWrapper<UserCouponPO> wrapper = new UpdateWrapper<>();
                    wrapper.eq("user_id", param.getUserId());
                    wrapper.eq("coupon_id", payInfo.getCouponId());
                    int coupon_count = userCouponMapper.update(tmp, wrapper);
                    if (coupon_count <= 0) {
                        log.info("使用优惠券失败！");
                        action.setRollbackOnly();
                        return false;
                    }
                }


                //扣除积分
                if (param.getPointsAmount() != null || param.getPointsAmount() >= 0) {
                    PointsInfoPO pointsInfo = new PointsInfoPO();
                    pointsInfo.setUserId(param.getUserId());
                    pointsInfo.setPoint(param.getPointsAmount() * -1);
                    pointsInfo.setPointName("支付单：" + param.getPayId() + " 抵扣");
                    boolean point_ret = pointsInfoService.addPoints(pointsInfo);
                    if (!point_ret) {
                        log.info("扣除积分失败");
                        action.setRollbackOnly();
                        return false;
                    }
                }

                //给轮询发送推送消息
                LinkedInquiry inquiry = new LinkedInquiry();
                inquiry.setDoCount(10);
                inquiry.setInquiryKey("sendpayresult");
                inquiry.setSupplierName("Order");
                inquiry.setSupplierIp("http://192.168.99.32:9006");
                inquiry.setUrl("order/orderhandle/receiverPayResult");
                inquiry.setTraceId(payInfo.getPayId());

                PayResultPush push = new PayResultPush();
                push.setPayId(payInfo.getPayId());
                push.setPayStatus("1");

                inquiry.setJsonParam(mapper.writeValueAsString(push));

                LinkedResult inquiryResult = scheduledTasksFeign.addInquiry(inquiry);
                if (!inquiryResult.isSuccess()){
                    log.info("创建推送信息失败！");
                    action.setRollbackOnly();
                    return false;
                }
            } catch (Exception e) {
                log.error("支付失败！", e);
                action.setRollbackOnly();
                return false;
            }
            return true;
        });
    }

    @Override
    public PayDetailResult queryPayDetail(String payId) throws Exception {
        PayInfoPO temp = payInfoMapper.selectById(payId);
        PayDetailResult result = new PayDetailResult();
        result.setPayId(payId);
        result.setOrderId(temp.getOrderId());
        result.setPayStatus(temp.getPayStatus());
        result.setMoneyAmount(temp.getMoneyAmount());
        result.setRealAmount(temp.getRealAmount());
        result.setCouponId(temp.getCouponId());
        result.setPayWayId(temp.getPayWayId());
        result.setCreateTime(temp.getCreateTime());
        result.setPointsAmount(temp.getPointsAmount());
        return result;
    }

    @Override
    public Integer queryPayStatusByPayId(@NonNull String payId) {
        return payInfoMapper.queryPayStatusByPayId(payId);
    }

    @Override
    public boolean cancelPayBill(@NonNull String payId) throws Exception {
        PayInfoPO tmp = new PayInfoPO();
        tmp.setPayId(payId);
        tmp.setPayStatus(3);
        return payInfoMapper.updateById(tmp) > 0;
    }

    @Override
    public boolean applyRefund(PayInfoPO payInfo) throws Exception {
        return transactionTemplate.execute(action -> {
            /**
             * 1、退积分
             * */
            if (0 < payInfo.getPointsAmount()) {
                QueryWrapper<PointsInfoPO> wrapper = new QueryWrapper<>();
                wrapper.eq("user_id", payInfo.getUserId());
                wrapper.eq("if_final", 1);
                PointsInfoPO temp = pointsInfoMapper.selectOne(wrapper);
                String oldPointId = temp.getPointsId();
                //1、保存最新的积分
                temp.setTotalPoints(temp.getTotalPoints() - payInfo.getPointsAmount());
                temp.setPoint(payInfo.getPointsAmount() * -1);
                temp.setPointsId(null);
                temp.setCreateTime(null);
                temp.setPointName("支付单：" + payInfo.getPayId() + " 退回");
                int new_count = pointsInfoMapper.insert(temp);
                if (new_count <= 0) {
                    log.info("保存更新后的积分失败！");
                    action.setRollbackOnly();
                    return false;
                }
                //2、修改原有的积分项
                PointsInfoPO newTmp = new PointsInfoPO();
                newTmp.setPointsId(oldPointId);
                newTmp.setIfFinal(0);
                int old_count = pointsInfoMapper.updateById(newTmp);
                if (old_count <= 0) {
                    log.info("修改原有的积分失败！");
                    action.setRollbackOnly();
                    return false;
                }
            }
            /**
             * 2、退优惠券
             * */
            if (!StringUtils.isEmpty(payInfo.getCouponId())) {
                UserCouponPO tmp = new UserCouponPO();
                tmp.setIfUsed(0);
                UpdateWrapper<UserCouponPO> wrapper = new UpdateWrapper<>();
                wrapper.eq("user_id", payInfo.getUserId());
                wrapper.eq("coupon_id", payInfo.getCouponId());
                int coupon_count = userCouponMapper.update(tmp, wrapper);
                if (coupon_count <= 0) {
                    log.info("退回优惠券失败！");
                    action.setRollbackOnly();
                    return false;
                }
            }
            /**
             * 3、退款
             * */
            paySupplyService = new WeiXinPay();
            boolean ret = paySupplyService.refund();
            if (!ret) {
                log.info("供应商支付失败！");
                action.setRollbackOnly();
                return false;
            }
            /**
             * 4、同步支付单数据
             * */
            PayInfoPO payTmp = new PayInfoPO();
            payTmp.setPayId(payInfo.getPayId());
            payTmp.setPayStatus(4);
            int pay_count = payInfoMapper.updateById(payTmp);
            if (pay_count <= 0) {
                log.info("修改支付单状态失败！");
                action.setRollbackOnly();
                return false;
            }
            return true;
        });
    }
}
